package cc.rengu.redp.flowable.listener;

import cc.rengu.redp.common.utils.SpringContextUtil;
import cc.rengu.redp.flowable.domain.FlowData;
import cc.rengu.redp.flowable.service.FlowDataService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import org.flowable.task.service.delegate.DelegateTask;
import org.flowable.task.service.delegate.TaskListener;

/**
 * 节点监听器基类，所有基本本机类的扩展监听处理程序，将被系统加载，并在流程配置器中完成开发配置。
 */
public abstract class AbstractBizListener implements ExecutionListener, TaskListener {

    private FlowDataService flowDataService = SpringContextUtil.getBean(FlowDataService.class);

    @Override
    public void notify(DelegateExecution execution) {
        FlowData flowData = flowDataService.getById(Long.valueOf(execution.getProcessInstanceBusinessKey()));
        if (flowData == null) {
            return;
        }

        EventInfo eventInfo = new EventInfo();
        eventInfo.setFlowInstId(execution.getProcessInstanceId());

        doExecuteByFlowData(flowData, new EventInfo());
    }

    @Override
    public void notify(DelegateTask delegateTask) {
        FlowData flowData = flowDataService.getFlowData(delegateTask.getProcessInstanceId());
        if (flowData == null) {
            return;
        }
        doExecuteByFlowData(flowData, new EventInfo());
    }

    private void doExecuteByFlowData(FlowData flowData, EventInfo eventInfo) {
        JSONObject oldFlowDataJo = JSON.parseObject(flowData.getFlowData());
        //复制一份数据，防止execution直接返回参数造成下面两对象比较不正确
        JSONObject newFlowDataJo = this.doExecute((JSONObject) oldFlowDataJo.clone(), eventInfo);
        if (!newFlowDataJo.equals(oldFlowDataJo)) {
            flowData.setFlowData(newFlowDataJo.toJSONString());
            flowDataService.modifiedFlowData(flowData);
        }
    }

    /**
     * 执行业务数据处理
     * @param flowData
     * @param eventInfo
     * @return
     */
    public abstract JSONObject doExecute(JSONObject flowData, EventInfo eventInfo);

    /**
     * 监听执行器名称
     * @return
     */
    public abstract String simpleDescription();
}
